using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static partial class ReferencePool
{
    private static readonly Dictionary<Type,ReferenceCollection> _referenceCollections = 
        new Dictionary<Type,ReferenceCollection>();

    /// <summary>
    /// 池子的数量
    /// </summary>
    public static int PoolCount
    {
        get { return _referenceCollections.Count; }
    }

    public static T Acquire<T>() where T:class,IReference,new()
    {
        return GetReferenceCollection(typeof(T)).Acquire<T>();
    }

    public static void Recycle(IReference reference)
    {
        if(reference == null) return;
        Type referenceType = reference.GetType();
        CheckReferenceType(referenceType);
        GetReferenceCollection(referenceType).Recycle(reference);
    }

    private static void CheckReferenceType(Type reference)
    {
        if(reference == null)
        {
            throw new NullReferenceException("引用为空!!!");
        }

        if(!reference.IsClass || reference.IsAbstract)
        {
            throw new InvalidCastException("目标不是类，或者不是抽象类");
        }

        if (!typeof(IReference).IsAssignableFrom(reference))
        {
            throw new InvalidCastException("引用无效!!!");
        }
    }

    private static ReferenceCollection GetReferenceCollection(Type referenceType)
    {
        if (referenceType == null)
        {
            throw new Exception("ReferenceType is invalid.");
        }

        ReferenceCollection referenceCollection = null;
        lock (_referenceCollections)
        {
            if (!_referenceCollections.TryGetValue(referenceType, out referenceCollection))
            {
                referenceCollection = new ReferenceCollection(referenceType);
                _referenceCollections.Add(referenceType, referenceCollection);
            }
        }

        return referenceCollection;
    }

    public static void Release()
    {
        foreach(var collection in _referenceCollections.Values)
        {
            collection.Release();
        }

        _referenceCollections.Clear();
    }
}
